package com.dark;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by tengxue on 15-9-30.
 */
public final class RedisUtil {

//    private static   Jedis jedis;

//    static {
//        if (jedis == null) {
//            jedis = new Jedis("localhost", 6379);
//            //权限认证
//            jedis.auth("admin");
//        }
//
//    }

    private RedisUtil() {

    }

    //Redis服务器IP
    private static String ADDR = "localhost";

    //Redis的端口号
    private static int PORT = 6379;

    //访问密码
    private static String AUTH = "";

    //可用连接实例的最大数目，默认值为8；
    //如果赋值为-1，则表示不限制；如果pool已经分配了maxActive个jedis实例，则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 1024;

    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例，默认值也是8。
    private static int MAX_IDLE = 200;

    //等待可用连接的最大时间，单位毫秒，默认值为-1，表示永不超时。如果超过等待时间，则直接抛出JedisConnectionException；
    private static int MAX_WAIT = 10000;

    private static int TIMEOUT = 10000;

    //数据库
    private static int DATABASE =1;

    //验证密码
    private static String  PASSWORD ="darkDev";

    //在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
    private static boolean TEST_ON_BORROW = true;

    private static JedisPool jedisPool = null;

    /**
     * 初始化Redis连接池
     */
    static {
        try {
            JedisPoolConfig config = new JedisPoolConfig();

            //连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
            config.setBlockWhenExhausted(true);

            //设置的逐出策略类名, 默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最大空闲连接数)
            config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy");

            //是否启用pool的jmx管理功能, 默认true
            config.setJmxEnabled(true);

            //MBean ObjectName = new ObjectName("org.apache.commons.pool2:type=GenericObjectPool,name=" + "pool" + i); 默认为"pool", JMX不熟,具体不知道是干啥的...默认就好.
            config.setJmxNamePrefix("pool");

            //是否启用后进先出, 默认true
            config.setLifo(true);

            //最大空闲连接数, 默认8个
            config.setMaxIdle(MAX_IDLE);

            //最大连接数, 默认8个
            config.setMaxTotal(8);

            //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
            config.setMaxWaitMillis(MAX_WAIT);

            //逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
            config.setMinEvictableIdleTimeMillis(1800000);

            //最小空闲连接数, 默认0
            config.setMinIdle(0);

            //每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
            config.setNumTestsPerEvictionRun(3);

            //对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断  (默认逐出策略)
            config.setSoftMinEvictableIdleTimeMillis(1800000);

            //在获取连接的时候检查有效性, 默认false
            config.setTestOnBorrow(false);

            //在空闲时检查有效性, 默认false
            config.setTestWhileIdle(false);

            //逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
            config.setTimeBetweenEvictionRunsMillis(-1);


            jedisPool = new JedisPool(config,ADDR,PORT,TIMEOUT,PASSWORD,DATABASE);
            System.out.println(jedisPool);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取Jedis实例
     *
     * @return Jedis
     */
    private synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis jedis = jedisPool.getResource();
                return jedis;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 添加数据
     *
     * @param key   键值
     * @param value 值
     * @return 成功与否的标识 ok表示成功
     */
    public static String insertData(String key, String value) {
        Jedis jedis = getJedis();
        String result = jedis.set(key, value);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 追加数据
     *
     * @param key   键值
     * @param value 值
     * @return  值的长度
     */
    public static Long apppendData(String key, String value) {
        Jedis jedis = getJedis();
        Long result = jedis.append(key, value);
        jedis.close();
        return result;
    }

    /**
     * 返回key对应的value
     * @param key 键值
     * @return 值
     */
    public static String getValue(String key){
        Jedis jedis = getJedis();
        String result=jedis.get(key);
        jedisPool.returnResource(jedis);
        return  result;
    }

    /**
     * 删除一个元素
     *
     * @param key
     * @return
     */
    public static Long deleteData(String key) {
        Jedis jedis = getJedis();
        Long result = jedis.del(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 给值+1 如果是字符则结果如何呢？
     *
     * @param key
     * @return
     */
    public static Long increaseData(String key) {
        Jedis jedis = getJedis();
        Long result = jedis.incr(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 插入Map值
     *
     * @param key
     * @param values
     * @return
     */
    public static String insertMapData(String key, Map<String, String> values) {
        Jedis jedis = getJedis();
        String result = jedis.hmset(key, values);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 根据Map中的键值获取值
     *
     * @param key
     * @param fields
     * @return
     */
    public static List<String> getValuesByKeys(String key, String... fields) {
        Jedis jedis = getJedis();
        List<String> result = jedis.hmget(key, fields);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 删除Map中的元素
     *
     * @param key
     * @param field
     * @return
     */
    public static Long deleteMapValue(String key, String... field) {
        Jedis jedis = getJedis();
        Long result = jedis.hdel(key, field);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取Map中元素的个数
     *
     * @param key
     * @return
     */
    public static Long getMapSize(String key) {
        Jedis jedis = getJedis();
        Long result = jedis.hlen(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取Map中key列表
     *
     * @param key
     * @return
     */
    public static Set<String> getMapKeys(String key) {
        Jedis jedis = getJedis();
        Set<String> result = jedis.hkeys(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取Map中value列表
     *
     * @param key
     * @return
     */
    public static List<String> getMapVaules(String key) {
        Jedis jedis = getJedis();
        List<String> result = jedis.hvals(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取List中的元素
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public static List<String> getListValues(String key, long start, long end) {
        Jedis jedis = getJedis();
        List<String> result = jedis.lrange(key, start, end);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 向List中添加元素,从head开始添加
     *
     * @param key
     * @param values
     * @return
     */
    public static Long addValue2ListHead(String key, String... values) {
        Jedis jedis = getJedis();
        Long result = jedis.lpush(key, values);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 向List中添加元素,从tail开始添加
     *
     * @param key
     * @param values
     * @return
     */
    public static Long addValue2ListTail(String key, String... values) {
        Jedis jedis = getJedis();
        Long result = jedis.rpush(key, values);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 向Set中添加元素
     *
     * @param key
     * @param values
     * @return
     */
    public static Long addValue2Set(String key, String... values) {
        Jedis jedis = getJedis();
        Long result = jedis.sadd(key, values);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 移除Set中的元素
     *
     * @param key
     * @param values
     * @return
     */
    public static Long deleteValueFromSet(String key, String... values) {
        Jedis jedis = getJedis();
        Long result = jedis.srem(key, values);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取Set中所有的元素
     *
     * @param key
     * @return
     */
    public static Set<String> getValuesFromSet(String key) {
        Jedis jedis = getJedis();
        Set<String> result = jedis.smembers(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 判断Set中是否包含指定的值
     *
     * @param key
     * @param value
     * @return
     */
    public static Boolean isExistFromSet(String key, String value) {
        Jedis jedis = getJedis();
        Boolean result = jedis.sismember(key, value);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取Set中随机一个元素
     *
     * @param key
     * @return
     */
    public static String getRandValueFromSet(String key) {
        Jedis jedis = getJedis();
        String result = jedis.srandmember(key);
        jedisPool.returnResource(jedis);
        return result;
    }

    /**
     * 获取Set中元素的个数
     *
     * @param key
     * @return
     */
    public static Long getSetSize(String key) {
        Jedis jedis = getJedis();
        Long result = jedis.scard(key);
        jedisPool.returnResource(jedis);
        return result;
    }
}
